package com.gitee.beiding.template_excel;

//模板单元

import java.util.*;

class TemplateCell {

    /**
     * 解析单元格
     *
     * @param s
     * @return
     */
    static TemplateCell parse(Object s) {
        TemplateCell r = new TemplateCell();
        if (s instanceof String) {
            TemplateCellParseUtils.Result array = TemplateCellParseUtils.parse((String) s);
            LinkedHashMap<String, LinkedHashSet<String>> map = array.getCheckJsMap();

            if (map.size() > 0) {

                //初始化
                r.arrayIndex = new ArrayIndex();
                r.arrayIndex.init(map);
                r.indexSet = map.keySet();

                //初始化?
                r.indexMax = new HashMap<>();

                for (String index : r.indexSet) {
                    r.indexMax.put(index, 0);
                }

            }
            //放入表达式
            r.expression = array.getExpression();
            r.commands = array.getCommands();

        } else {
            r.singleResult = new RenderHolder(r, "", s);
        }
        return r;
    }

    private TemplateCell() {

    }

    //单元格指令
    private List<String> commands;

    //单元格表达式
    private String expression;

    //数组索引
    private ArrayIndex arrayIndex;

    private Set<String> indexSet;

    private Map<String, Integer> indexMax;

    private RenderHolder singleResult;

    private DB db;


    Map<String, Integer> getIndexMax() {
        return indexMax;
    }

    RenderHolder getSingleResult() {
        return singleResult;
    }

    //运算
    void exe() {

        if (expression != null) {

            Map<String, Integer> condition = new HashMap<>();

            if (arrayIndex != null) {

                db = new DB(indexSet);

                while (arrayIndex.autoIncrement()) {

                    for (String s : indexMax.keySet()) {
                        int v = (Integer) Js.get(s);
                        Integer currentMax = indexMax.get(s);
                        if (currentMax == null || v > currentMax) {
                            indexMax.put(s, v);
                        }
                        condition.put(s, v);
                    }

                    //放入结果集
                    try {
                        db.putValue(condition, Js.exe(expression));
                    } catch (Exception e) {//  这里可能会数组越界,直接忽略即可
                        // System.err.println(condition + "    " + expression);
                        //System.err.println(expression);
                        // db.putValue(condition, null);
                    }

                }

                //清空临时变量
                arrayIndex.clear();

            } else {
                try {
                    //计算单个节点
                    singleResult = new RenderHolder(this, "", Js.exe(expression));
                } catch (Exception e) {
                    // System.err.println(expression);
                }
            }
        }

    }

    /*
      建立索引
      返回值中的有关参量
     */
    RenderHolder get(Map<String, Integer> index) {

        RenderHolder r;

        if (arrayIndex == null) {
            r = singleResult;
        } else {
            r = db.andValue(this,index);
        }




        if (commands != null) {//处理指令

            if (r == null) {
                return null;
            }

            // 断言 r一定为字符串类型
            String s = (String) r.getValue();

            Iterator<String> iterator = commands.iterator();
            if (iterator.hasNext()) {

                String command = iterator.next();
                try {
                    Object exe = Js.exe(command);

                    //表达式中只有一个指令没有其他
                    if ((s.replace(command, "").trim().equals(""))) {
                        //含有指令的不能合并
                        return new RenderHolder(this, UUID.randomUUID().toString(), exe);
                    }
                    if (exe == null) {
                        s = s.replace(command, "");
                    } else {
                        s = s.replace(command, exe.toString());
                    }

                    while (iterator.hasNext()) {
                        try {
                            command = iterator.next();
                            exe = Js.exe(command);
                            if (exe == null) {
                                s = s.replace(command, "");
                            } else {
                                s = s.replace(command, exe.toString());
                            }
                        } catch (Exception ignore) {
                        }
                    }

                } catch (Exception e) {
                    System.out.println("指令执行错误");
                    e.printStackTrace();
                }

            }
            return new RenderHolder(this, UUID.randomUUID().toString(),s);
        }

        return r;

    }


}

